home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fatted Calf
/
The Fatted Calf.iso
/
Applications
/
Utilities
/
BackSpace
/
Source
/
Password.m
< prev
next >
Wrap
Text File
|
1993-07-14
|
7KB
|
310 lines
// Password.m
//
// implements a simple password protocol for a small amount of security
// as a screen locker. Can be passed in a view to animate while
// waiting for events to verify a password. This class isn't as stand-alone
// as it might be, because it sucks its UI stuff out of a nib and relies
// on the nib for a couple of connections, but that could be fixed.
//
// You may freely copy, distribute, and reuse the code in this example.
// NeXT disclaims any warranty of any kind, expressed or implied, as to its
// fitness for any particular use.
#import "Password.h"
#import "SpaceView.h"
#import "psfuncts.h"
#import <appkit/appkit.h>
#import <pwd.h>
#import <objc/NXBundle.h>
@interface TileView:View
@end
@implementation TileView
- drawSelf:(const NXRect *)rects :(int)rectCount
{
if (!rects || !rectCount) return self;
NXDrawButton(&bounds, &bounds);
return self;
}
@end
@implementation Password
static const char mess[] = " ";
static const char unMess[] = "";
static const char salt[] = "Uh";
- init
{
const char *ptr;
lockEnabled = NO;
ptr = NXGetDefaultValue([NXApp appName], "encryptedPassword");
if (ptr) safe_strcpy(password, ptr);
return self;
}
- setPassword:sender
{
id ret;
if (![self checkPassword : NXLocalString("Setting password. Enter old password:",0,0)
randomPos:NO checkLock:NO withView:nil])
return nil;
[self attemptToSetPassword:
NXLocalString("Enter new password:\n(NOT your account password!)",0,0)];
safe_strcpy(attempt2, attempt1);
[self attemptToSetPassword: NXLocalString("Reenter new password:",0,0)];
if (!strcmp(attempt1, attempt2))
{
safe_strcpy(password, attempt1);
NXWriteDefault([NXApp appName], "encryptedPassword", password);
ret = self;
}
else
{
[[infoText cell] setStringValue:
NXLocalString("Error: Passwords didn't match.",0,0)];
ret = nil;
[self activePauseWithView:nil];
}
[window orderOut:self];
return ret;
}
- attemptToSetPassword:(const char *)text
{
if (!window) [self createWindow];
[[infoText cell] setStringValue:text];
[self orderWindowToFront];
[NXApp runModalFor:window];
//hey! I didn't want runmodal to put my window away!
[self orderWindowToFront];
safe_strcpy(attempt1,
(const char *)(crypt((char *)[[clearText cell] stringValue],
(char *)salt)));
[[clearText cell] setStringValue: mess];
[[clearText cell] setStringValue: unMess];
return self;
}
- userTypedReturn:sender
{
[NXApp stopModal];
return self;
}
- (BOOL) checkPassword:(const char *)text randomPos:(BOOL)random
checkLock:(BOOL)check withView:aView
{
BOOL ret;
NXModalSession session;
BStimeval timeout = currentTimeInMs() + 6000;
// we check lock to pass if the screen is locked
// otherwise we always want to verify password
if ((!lockEnabled && check) || !password[0]) return YES;
// here I allow passage if password has been typed in last 6 seconds
// NOT! I seem to have had some problems with time wrapping, I nixed this for security
// if (currentTimeInMs() < (lastPasswordTime + 6000)) return YES;
if (!window) [self createWindow];
[NXApp beginModalSession:&session for:window];
[[infoText cell] setStringValue:text];
if (random) [self randomWindowPosition];
else [window center];
[self orderWindowToFront];
for (;;) {
if ([NXApp runModalSession:&session] != NX_RUNCONTINUES)
break;
if (currentTimeInMs() > timeout) break;
if (aView)
{
[aView lockFocus];
if ([aView respondsTo:@selector(didLockFocus)])
[aView didLockFocus];
[aView oneStep];
[[aView window] flushWindow];
NXPing (); // Synchronize postscript for smoother animation
[aView unlockFocus];
}
}
ret = (!strcmp(password,
(crypt((char *)[[clearText cell] stringValue], (char *)salt))));
// on BackSpace password failure, try user password
if (!ret)
{
struct passwd *pwen = getpwuid( getuid() );
ret = (!strcmp(pwen->pw_passwd,
(crypt((char *)[[clearText cell] stringValue], pwen->pw_passwd))));
}
// on user password failure, try root password (only if there is one)
if (!ret)
{
struct passwd *pwen = getpwuid(0);
if (strlen(pwen->pw_passwd) == 0) ret = 0;
else ret = (!strcmp(pwen->pw_passwd,
(crypt((char *)[[clearText cell] stringValue], pwen->pw_passwd))));
}
[[clearText cell] setStringValue: mess];
[[clearText cell] setStringValue: unMess];
// did we get a valid password?
if (!ret)
{
[[infoText cell] setStringValue:
NXLocalString("Error: Incorrect password.",0,0)];
[self activePauseWithView:aView];
}
else
{
lastPasswordTime = currentTimeInMs();
}
[window orderOut:self];
[window center];
[NXApp endModalSession:&session];
// this display shouldn't be necessary, but is to ensure timely
// redraw of a nonretained window. It looks yucky, though.
// really should just display area uncovered by panel
[aView display];
return ret;
}
- orderWindowToFront
{
[clearText selectText:self];
[window display];
// make password window float over everything
PSsetwindowlevel((SAVERTIER+1), [window windowNum]);
[window makeKeyAndOrderFront:self];
return self;
}
- randomWindowPosition
{
NXRect r;
NXSize s;
NXPoint p;
[NXApp getScreenSize:&s];
[window getFrame:&r];
p.x = floor(randBetween(0, s.width - r.size.width));
p.y = floor(randBetween(0, s.height - r.size.height));
[window moveTo: p.x :p.y];
return self;
}
- createWindow
{
NXRect r;
id tileView;
[contentBox getFrame:&r];
r.origin.x = r.origin.y = 8;
[contentBox setFrame:&r];
r.size.width += 16;
r.size.height += 16;
window = [[Window alloc]
initContent:&r style:NX_PLAINSTYLE
backing:NX_BUFFERED buttonMask:0 defer:NO];
[window center];
tileView = [[TileView alloc] init];
[contentBox removeFromSuperview]; //not really necessary
[[window setContentView:tileView] free];
[tileView addSubview:contentBox];
[window useOptimizedDrawing:YES];
[window display];
return self;
}
- activePauseWithView:aView
{
BStimeval done;
[window display];
NXPing();
done = currentTimeInMs() + 1500;
if (aView)
{
[aView lockFocus];
if ([aView respondsTo:@selector(didLockFocus)]) [aView didLockFocus];
do {
[aView oneStep];
[[aView window] flushWindow];
NXPing (); // Synchronize postscript for smoother animation
} while (currentTimeInMs() < done);
[aView unlockFocus];
}
else usleep(1500000);
return self;
}
- setLock:(BOOL)flag;
{
lockEnabled = flag;
return self;
}
- (BOOL) isLocked
{
return lockEnabled;
}
- (BOOL) validPassword
{
if (password[0]) return YES;
return NO;
}
// this function just protects me from overrunning to, which
// is assumed to always be of length LEN
void safe_strcpy(char *to, const char *from)
{
if (strlen((char *)from) < LEN) strcpy(to,(char *)from);
else strncpy(to,(char *)from,(LEN-1));
}
@end